package com.zzh.h265toupin

import android.app.Activity
import android.content.Context
import android.media.MediaCodec
import android.media.MediaFormat
import android.util.Log
import android.view.Surface
import android.widget.Toast
import com.zzh.h265toupin.sockets.SocketPullClient
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch


class H265Decode(private val surface: Surface) {

    private var socketPullClient: SocketPullClient? = null
    private lateinit var mediaCodec: MediaCodec

    init {
        initDecoder()
    }

    private var connectCallback: ((connected: Boolean) -> Unit)? = null


    fun setConnectCallback(connectCallback: (connected: Boolean) -> Unit) {
        this.connectCallback = connectCallback
    }

    fun startPlay(url: String) {
        Log.d("TAG_H265Decode", "startPlay:$url")
        socketPullClient = SocketPullClient(url) {
            Log.d("TAG_H265Decode", "Decode:${it.contentToString()}")
            CoroutineScope(Dispatchers.IO).launch {
                play(it)
            }
        }
        connectCallback?.let { socketPullClient!!.setConnectCallback(it) }
        socketPullClient!!.start()
    }

    private fun initDecoder() {
        mediaCodec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_HEVC)
        val format =
            MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_HEVC, 1012, 2000).apply {
                setInteger(MediaFormat.KEY_BIT_RATE, 500000)
                setInteger(MediaFormat.KEY_FRAME_RATE, 20)
                setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1)
            }
        mediaCodec.configure(format, surface, null, 0)
        mediaCodec.start()
    }

    private fun play(frame: ByteArray?) {
        frame ?: return
        try {
            val channel = mediaCodec.dequeueInputBuffer(10000)
            if (channel >= 0) {
                val inputBuffer = mediaCodec.getInputBuffer(channel) ?: return
                inputBuffer.clear()
                inputBuffer.put(frame, 0, frame.size)
                mediaCodec.queueInputBuffer(channel, 0, frame.size, System.currentTimeMillis(), 0)
            }
            val bufferInfo = MediaCodec.BufferInfo()
            val outChannel = mediaCodec.dequeueOutputBuffer(bufferInfo, 100000)
            while (outChannel >= 0) {
                mediaCodec.releaseOutputBuffer(outChannel, true)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun close() {
        socketPullClient?.close()
        mediaCodec.stop()
    }

}